import networkx as nx
from utils.read_graph import read_graph
import re


class TableNameReplace:
    def __init__(self):
        self.__index = None
        self.__start_node = None
        self.__keywords = None
        self.__message = {'is_success': True,
                          'is_miss': False,
                          'error_index_list': []
                          }
        self.__graph = read_graph()
        self.__new_name_list = None

    def __get_key_words(self, row_string):
        return row_string.strip('\n').strip('\t').strip('_').split('_')

    def __check_if_stop(self, G, start_node):
        next_nodes = [i for i in G.neighbors(start_node)]
        for next_node in next_nodes:
            if 'STOP' in G.edges[start_node, next_node]['names']:
                return True
        return False

    def __check_regex(self, name, res):
        ll = re.findall(name.strip('REGEX'), res, flags=0)
        return len(ll) != 0 and ll[0] == res

    # 字符串匹配的三种情况
    # 第一种 有一个字符子串完全没有匹配到 失败
    # 第二种 字符串没有匹配到图的终点 失败
    # 第三种 字符串完全匹配并走到终点 成功

    def __check_graph(self, row_str):
        # dwd_newsapp_active_user_d_i_p7dk
        row_string = row_str
        G = self.__graph
        key_words = self.__get_key_words(row_string)
        self.__keywords = key_words
        start_node = 0
        index = 0
        if_find = False
        while index < len(key_words):
            if_find = False
            next_nodes = [i for i in G.neighbors(start_node)]
            for next_node in next_nodes:
                flag = 0
                for name in G.edges[start_node, next_node]['names']:
                    if key_words[index] == name or 'REGEX' in name and self.__check_regex(name, key_words[index]):
                        start_node = next_node
                        if_find = True
                        flag = 1
                        break
                if flag:
                    break
            if not if_find and index < len(key_words):
                self.__start_node = start_node
                self.__index = index
                return False
            index += 1
        if not self.__check_if_stop(G, start_node):
            self.__start_node = start_node
            return False
        return index == len(key_words) and if_find and self.__check_if_stop(G, start_node)

    def __get_neighbor_names(self, start_node):
        next_nodes = [i for i in self.__graph.neighbors(start_node)]
        res = []
        for next_node in next_nodes:
            for name in self.__graph.edges[start_node, next_node]['names']:
                res.append(name)
        return res

    def get_name_from_list(self, name_list):
        res = ''
        for name in name_list:
            res += name
            res += '_'
        return res.strip('_')

    def __get_new_name_list(self, row_string, is_first=False):
        self.__table_name = row_string
        # print(self.__table_name, 666)
        self.__index = None
        self.__start_node = None
        self.__is_correct = self.__check_graph(row_string)
        if not self.__is_correct and self.__start_node != None and self.__index != None:

            if is_first:
                self.__message['is_success'] = False
            self.__message['error_index_list'].append(self.__index + 1)
            # 第一种 有一个字符子串完全没有匹配到 失败
            # 当前失败的单词在A层
            # 找到A+1层的所有边上的两个节点与边上的单词 word_dic

            A_neighbor_nodes = [i for i in self.__graph.neighbors(self.__start_node)]
            A_names = []
            for A_node in A_neighbor_nodes:
                for ii in self.__graph.edges[self.__start_node, A_node]['names']:
                    A_names.append(ii)

            from collections import defaultdict
            word_dic = defaultdict(list)
            for A_node in A_neighbor_nodes:
                for B_node in self.__graph.neighbors(A_node):
                    for ii in self.__graph.edges[A_node, B_node]['names']:
                        word_dic[ii].append((A_node, B_node))

            # 判断失败单词的后一个单词是否在 word_dic
            key_words = self.__get_key_words(self.__table_name)
            flag = False
            if self.__index < (len(key_words) - 1):
                if key_words[self.__index + 1] in word_dic.keys():
                    flag = True

            new_name_list = []
            # 1 不在word_dic中，说明 失败单词后一个单词不可以在A+1层找到:
            if not flag:
                # 1.1 把A层所有的单词分别替换旧名称中self.__index的位置，得到结果列表，返回
                for name in A_names:
                    temp = key_words
                    temp[self.__index] = name
                    new_name_list.append(self.get_name_from_list(temp))
                return new_name_list
            # 2 在word_dic中，说明 失败单词后一个单词可以在A+1层找到:
            else:
                tt = word_dic[key_words[self.__index + 1]]
                for tt1 in tt:
                    left_node = tt1[0]
                    temp_name_list = self.__graph.edges[self.__start_node, left_node]['names']
                    for name in temp_name_list:
                        temp = key_words
                        temp[self.__index] = name
                        new_name_list.append(self.get_name_from_list(temp))
                return new_name_list

        elif not self.__is_correct and self.__start_node != None:
            if is_first:
                self.__message['is_success'] = False

            A_neighbor_nodes = [i for i in self.__graph.neighbors(self.__start_node)]
            A_names = []
            for A_node in A_neighbor_nodes:
                for ii in self.__graph.edges[self.__start_node, A_node]['names']:
                    A_names.append(ii)
            key_words = self.__get_key_words(self.__table_name)
            new_name_list = []
            import copy
            for name in A_names:
                temp = copy.deepcopy(key_words)
                temp.append(name)
                new_name_list.append(self.get_name_from_list(temp))
            return new_name_list

        else:
            self.__message['is_success'] = True
            return [row_string]

    def __filter_stop(self, row_string):
        while 'STOP' in row_string:
            row_string = row_string.strip('STOP')
            row_string = row_string.strip('_')
        return row_string.strip('_')

    def check(self, row_string):

        # self.__message = {'is_success': True,
        #                   'is_miss': False,
        #                   'error_index_list': []
        #                   }

        key_words = self.__get_key_words(row_string)
        new_name_list = self.__get_new_name_list(row_string, is_first=True)
        # print(new_name_list)
        if self.__message['is_success']:
            print('当前名称符合规范！')
            return
        suc_res = []
        pre_record = ''
        while True:
            to_be_checked = []
            if pre_record == new_name_list[0]:
                break
            pre_record = new_name_list[0]
            # print('*' * 10)
            for new_name in new_name_list:
                # print(new_name)
                self.__message['is_success'] = False
                temp_name_list = self.__get_new_name_list(new_name, is_first=False)
                # print(temp_name_list)
                if self.__message['is_success']:
                    suc_res.append(new_name)
                    to_be_checked += temp_name_list
                else:
                    to_be_checked += temp_name_list
            # print('*' * 10)
            new_name_list = to_be_checked

        print('您的输入为：', row_string)
        print('您的输入错误，不符合规范！')

        if len(suc_res) == 0:
            print()
        print('已经智能为您推荐以下候选方案: ')
        suc_res.sort(key=lambda x: x[0:3])
        for nn in suc_res:
            print(self.__filter_stop(nn))
